#pragma once
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<cstdlib>
#include"log.hpp"
const int backlog=1;
extern Log lg;
enum
{
    SOCK_ERR=1,
    BIND_ERR,
    LINSTEN_ERR
};
class Sock
{
    private:
    int sockfd_;
    public:
    Sock()
    {

    }
    ~Sock()
    {

    }
    void Socket()
    {
        sockfd_=socket(AF_INET,SOCK_STREAM,0);
        if(sockfd_<0)
        {
            lg(FATAL,"Create socket fail! errno is %d, errstring is : %s",errno,strerror(errno));
            exit(SOCK_ERR);
        }
        int opt=1;
        setsockopt(sockfd_,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    }
    void Bind(uint16_t port)
    {
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_addr.s_addr=INADDR_ANY;
        local.sin_family=AF_INET;
        local.sin_port=htons(port);
       ssize_t n= bind(sockfd_,(sockaddr*)&local,sizeof(local));
       if(n<0)
       {
        lg(FATAL,"Bind socket fail!! errno is:%d, errstring is: %s",errno,strerror(errno));
        exit(BIND_ERR);
       }

    }
    void Linsten()
    {
       int n= listen(sockfd_,backlog);
       if(n<0)
       {
        lg(FATAL,"Linsten fail !! errno is:%d, errstring is: %s ",errno,strerror(errno));
        exit(LINSTEN_ERR);
       }
    }
    int Accept(uint16_t*port,std::string*ip)
    {
        struct sockaddr_in peer;
        socklen_t len=sizeof(peer);
      int newfd=  accept(sockfd_,(sockaddr*)&peer,&len);
      if(newfd<0)
      {
        //lg(WARNING,"Accept fail !! errno is:%d, errstring is: %s",errno,strerror(errno));
        return -1;
      }
       *port=ntohs(peer.sin_port);
       char buffer[SIZE];
      inet_ntop(AF_INET,&peer.sin_addr,buffer,sizeof(buffer));
      *ip=buffer;
      return newfd;
    }
    bool Connect(const std::string& ip,const uint16_t&port)
    {
        struct sockaddr_in peer;
        memset(&peer,0,sizeof(peer));
        peer.sin_family=AF_INET;
        peer.sin_port=htons(port);
        inet_pton(AF_INET,ip.c_str(),&peer.sin_addr);
       int n= connect(sockfd_,(sockaddr*)&peer,sizeof(peer));
       if(n<0)
       {
        lg(WARNING,"Connect to [ ip:%s,port:%d ] fail!! errno is :%d, errstring is:%s",ip.c_str(),port,strerror(errno));
       return false;
       }
       return true;
    }
    void Close()
    {
        close(sockfd_);
    }
    int Fd()
    {
        return sockfd_;
    }

    
};